﻿using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;

namespace AllInOne
{
    public class CSharpAppAdapter : MarshalByRefObject
    {
        public CSharpAppAdapter()
        {
        }

        public void Execute(string content, Proxy p)
        {
            Console.SetOut(new HtmlConsoleWriter(p));

            var md5 = System.Security.Cryptography.MD5.Create();
            var hash = BitConverter.ToString(md5.ComputeHash(Encoding.UTF8.GetBytes(content)));

            if (hash != this.AppHash)       //Recompile code when hash differs
            {
                var result = Compiler.CompileAssembly(content);

                foreach (CompilerError error in result.Errors)
                {
                    p.ConsoleWrite(error.ErrorText, true);
                }

                if (result.Errors.Count < 1)
                {
                    AppAssembly = result.CompiledAssembly;
                }

                AppHash = hash;
            }

            Run(p);
        }

        private void Run(Proxy p)
        {
            var entry = this.AppAssembly.GetTypes().Select(t => t.GetMethod("Main", BindingFlags.Static | BindingFlags.NonPublic))
    .Single(m => m != null);

            var parameters = entry.GetParameters();
            if (parameters.Length > 0 && p != null)   //Parameter required to run 
            {
                //entry.Invoke(null, new object[] { new string[] { arguments } });
                entry.Invoke(null, new object[] { null });
            }
            else
            {
                entry.Invoke(null, new object[] { null });
            }
        }

        public System.Reflection.Assembly AppAssembly { get; private set; }

        public string AppHash { get; private set; }
    }
}
